package chinaums.web.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.bouncycastle.util.encoders.UrlBase64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.alibaba.fastjson.JSON;

import chinaums.common.test.ByteUtils;
import chinaums.common.util.DateUtil;
import chinaums.entity.CodeMsg;
import chinaums.service.IUrlService;
import chinaums.service.InsertInfoService;
import chinaums.service.impl.InsertInfoServiceImpl;
import chinaums.service.impl.SelectInfoServiceImpl;

//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
import net.sf.json.JSONObject;

/**
 * 将调用接口返回的数据插入到数据库
 * 
 * @author Administrator
 * 
 */

@Controller
@RequestMapping("/Insert1")
public class InsertInfoControllor1 {
	private Logger logger = LoggerFactory
			.getLogger(InsertInfoControllor1.class);

	@Autowired
	private InsertInfoServiceImpl insertInfoService;
	@Autowired
	private SelectInfoServiceImpl selectInfoService;
	@Autowired
	private IUrlService urlservice;

	private final static String PRI_KEY = "30820277020100300d06092a864886f70d0101010500048202613082025d02010002818100a63c8a428726ac9f4399491db6469a5b6cab007bd16ace16c5d40a9afe2094d79f61965f551e537df6c4e74df10362409e3a5d3492cbbd8a2824e421c0854296bb0dbc75ee1c71f38b0a070791211a612ca370548ef0391740060104ab9b1253cf2c14c4d402d0acf0921a9d85b82dfcf008af22ded0279dfdf39ffc4fbe70ab02030100010281810099713639b460996424d47fade24b073dae6fa571a4dace422cf6cd97454d33b658128ee78e3d00da3b8682eee9b1b2e66c66f913871072f2ec9d28ca92d72e9f4d309c95897103594c1dba891d4cd559a779ef9985aa4ce82880cf06cd8592ad2513e1322fb09f78de53c77ce02f0ad9e1779829567cd7ba539770966cee47c9024100ea7bdd39e91a14ad9f714b2177d756310a58debf01d0d21bdf18a5141ee0fdfc40fa68a4589c2eb8eb42cf1c99fd9c152a1933a3ca17a7c5ac3dbcf23d0cf8c7024100b57d83690126d2b0a139a625c5c6b295e3fdb6827f86be22c8c72c29c78fb23a0b12aa03cfb9f87c22e125e118a35406e4a8329d7129544a24a222c7dce2ccfd02410090ab0f18959ac3bb432df0fe9b23be47cf6c79313b7b8cc62964d9248ad0a1a32aabd437e17baacfe84675e5dd943ce249f0f68d4d383f0894761ac711a7992d02407279fafbaec848393558e19e0dc4293d3694001d0c4777830555ec5b660f13825d1da6b3c4c12f254df2ea2bb398c2159f0120fc0236e97de2e18a42bae72c19024002611da3fc65fe20303a9a6710a858f8b81801d879333de5d6d9d30b40ef889422f5f18f4e77fdc8d0f8c2d4f0769f451305dde6a36901e675c102bcb566c05d";

	private final static String PUB_KEY = "30819f300d06092a864886f70d010101050003818d0030818902818100a1d63a7f19a91759572dd2e5d00e0e22fa5f7cc18fbcca99a21225701c1ebe275744c4d5a4cfbe624c65423780d06974c3f4fa5b60cf3590bfeaba9f80a8abc04c98ee5809c5fd2d09f307f63b358549e5d0835da11decec7be57d578416994c6b118e2b4a3ee015d7b11bfe771275f71a395dd9dfc248c2f3c8f03f7081b5c30203010001";
	// 测试路径
	private static final String url = "http://144.131.252.157:7017/adv-sms/sms/gen/genUrls";

	private static final String newUrl = "http://144.131.252.157:7017/adv-sms/sms/";
	// 生产 路径
	// private static final String url =
	// "http://198.17.1.100:8016/adv-sms/sms/gen/genUrls";

	// private static final String newUrl =
	// "http://198.17.1.100:8016/adv-sms/sms/";
	private String check = "";

	/**
	 * 将返回的数据插入到数据库
	 * 
	 * @param response
	 * @param request
	 * @param taskid
	 * @return
	 * @throws Exception
	 */
	// produces = "text/plain; charset=UTF-8"
	@RequestMapping(value = "/InsertInfo")
	public void getData(String id, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		// id="1";
		long one = System.currentTimeMillis();////////////////////////////////////////////////////////////////////////////1
		CodeMsg msg = new CodeMsg();
		Map<String, String> map = new HashMap<String, String>();
		map = selectInfoService.getData(id);// 通过ID得到请求参数
		map.put("CURRENTTIME", DateUtil.getCurrentTime());
		// System.out.println("1111111111111" + map);
		// String CHANNEL = map.get("CHANNEL");
		// String channel=CHANNEL="106101";
		map.put("channel", "106101");
		String channel = map.get("channel");
		// String FEEDBACKURL = map.get("FEEDBACKURL");
		// String feedbackUrl = FEEDBACKURL;
		String feedbackUrl = map.get("feedbackUrl");
		// String COUNT = map.get("COUNT");
		// String count = COUNT;
		String count = map.get("count");
		String CURRENTTIME = map.get("CURRENTTIME");
		String currentTime = CURRENTTIME;// 当前时间
		System.out.println("当前时间：" + currentTime);
		// {CHANNEL=106101, COUNT=2, CURRENTTIME=20170609134332,
		// FEEDBACKURL=www.baidu.com}
		// String channel = "106101", feedbackUrl = "www.baidu.com", count =
		// "100", currentTime = "20170609112600";

		// 私钥签名
		String signData = String.format(
				"channel=%s&feedbackUrl=%s&count=%s&currentTime=%s", channel,
				feedbackUrl, count, currentTime);
		byte[] sign = sign(signData.getBytes(),
				ByteUtils.hexString2ByteArray(PRI_KEY));
		String token = new String(UrlBase64.encode(sign));

		String param = signData + "&token=" + token;
		// 返回报文ysq
		String rspResult = doHttpPost(url, param, "UTF-8", id);// rspResult="success","fail01","fail02"
		JSONObject rspJson = JSONObject.fromObject(rspResult);

		String rspCode = rspJson.getString("rspCode");
		String rspMsg = rspJson.getString("rspMsg");
		List ids = (List<String>) rspJson.get("ids");
		token = rspJson.getString("token");

		String signResult = null;
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < ids.size(); i++) {
			sb.append(ids.get(i));
			if (i + 1 < ids.size()) {
				sb.append(",");
			}
		}

		boolean verfy = verify(sb.toString().getBytes(),
				ByteUtils.hexString2ByteArray(PUB_KEY),
				UrlBase64.decode(token.getBytes("UTF-8")));

		System.out.println(verfy);
		long two = System.currentTimeMillis();///////////////////////////////////////////////////////////////////////////////////2

		// System.out.println("111111111111111111111111111111111111"+rspResult);/////////////////////////////
		long re1 = System.currentTimeMillis();
		check = urlservice.insertUrl(id);
		long re2 = System.currentTimeMillis();
		// System.out.println("ysq......................."+(two-one)+"ms");
		logger.info("总的时间" + (two - one) + "ms");////////////////////////////////////////////////////////总时间
		// System.out.println("re......................."+(re2-re1)+"ms");
		logger.info("re" + (re2 - re1) + "ms");
		if (check.equals("success")) {
			Map<String, Object> map2 = new HashMap<String, Object>();
			map2.put("flg", 1);
			map2.put("id", id);
			selectInfoService.changebyid(map2);
			// attr.addFlashAttribute("msg", "跟踪配置成功!");
			msg.setCode("success");
			response.getWriter().print(JSON.toJSONString(msg));
		} else if (check.equals("fail01")) {
			Map<String, Object> map2 = new HashMap<String, Object>();
			map2.put("flg", 2);
			map2.put("id", id);
			selectInfoService.changebyid(map2);
			// attr.addFlashAttribute("msg", "跟踪配置失败!");
			msg.setCode("fail01");
			response.getWriter().print(JSON.toJSONString(msg));
		} else {
			Map<String, Object> map2 = new HashMap<String, Object>();
			map2.put("flg", 2);
			map2.put("id", id);
			selectInfoService.changebyid(map2);
			// attr.addFlashAttribute("msg", "跟踪配置失败!");
			msg.setCode("fail02");
			response.getWriter().print(JSON.toJSONString(msg));
		}

	}

	public String doHttpPost(String url, String content, String chartset,
			String id) {

		HttpURLConnection connection = null;
		try {
			long start = System.currentTimeMillis();///////////////////////////////////////访问路径开始的时间
			// System.out.println("request:" + url);
			// System.out.println("请求报文:\n" + content);
			connection = (HttpURLConnection) new URL(url).openConnection();
			connection.setDoOutput(true);
			connection.setDoInput(true);
			connection.setRequestMethod("POST");
			connection.setUseCaches(false);
			connection.setInstanceFollowRedirects(true);
			connection.setRequestProperty("Accept-Charset", chartset);

			// connection.setRequestProperty("Content-Type",
			// "application/json");
			connection.connect();
			OutputStream out = connection.getOutputStream();
			out.write(content.getBytes(chartset));

			out.flush();
			out.close();
			// /////////////
			long aa = System.currentTimeMillis();
			String response = getResponseText(connection, chartset);
			// ///////////////////
			long bb = System.currentTimeMillis();
			// System.out.println("////////////////////////////////////"+(bb-aa)/1000+"s");
			// System.out.println("2222222222222222222222222222222222"+response);
			// System.out.println("1111111111111111111111111111111111111111111111111111111111111111111"+id);
			long wq = System.currentTimeMillis();//////////////////////////////////////////////////////////////////////
			Map<String, Object> map = JSON.parseObject(response, Map.class);
			String rspMsg = (String) map.get("rspMsg");
			rspMsg = new String(rspMsg.getBytes("gbk"), "utf-8");
			map.put("id", id);
			map.put("rspMsg", rspMsg);

			List<String> list = (List<String>) map.get("ids");
			// System.out.println("listaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + list);
			// 测试: http://210.22.91.77:7018/adv-sms/sms/{id}
			StringBuffer sb = new StringBuffer();
			// 遍历返回参数ids
			
			for (int i = 0; i < list.size(); i++) {
				sb.append(newUrl);

				sb.append(list.get(i)); // ["vQN","vQO"]

				if (i < list.size() - 1) {
					sb.append(",");
				}
				map.put("ids", sb.toString());// 将拼接后的ids放到map,这边的数据ids的值需要转成String类型

				// System.out.println("111111111111111111111111111111" + sb);

			}
			long wq1 = System.currentTimeMillis();
			logger.info("遍历ids花费的时间" + ((wq1 - wq)) + " ms");
			// System.out.println("map++++++++++"+map);

			// 将返回的参数插入到数据库/////////////////////////////////////////////////
			long we = System.currentTimeMillis();
			long a = insertInfoService.insertInfo(map);
			long we1 = System.currentTimeMillis();
			logger.info("将数据插入数据库花费的时间" + ((we1 - we)) + " ms");

			 System.out.println("插入数据：" + a);
			/*long  re1=System.currentTimeMillis();
			 check = urlservice.insertUrl(id);///////////////////////////////
			 long  re2=System.currentTimeMillis();
				logger.info("rel...........: " + ((re2 - re1))
						+ " ms"); 
		*/
			long end = System.currentTimeMillis();
			// System.out.println("doHttpPost cost time: " + ((end -
			// start)-(bb-aa)) + " ms");
			logger.info("doHttpPost cost time: " + ((end - start))
					+ " ms");
			logger.info("访问接口" + ((end - start)-(wq1 - wq)-(we1 - we))
					+ " ms");
			
			// String result=urlController.add(map,id);
			return response;
			// return response;//changlianjie ===> success、fail 02

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			connection.disconnect();

		}

		return null;
	}

	private static String getResponseText(URLConnection connection,
			String chartset) {
		BufferedReader reader = null;
		StringBuilder sbd = null;
		try {
			reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream(), chartset));
			String line;
			sbd = new StringBuilder();
			while ((line = reader.readLine()) != null) {
				sbd.append(line).append("\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		if (sbd == null)
			return null;

		return sbd.toString();
	}

	/**
	 * 私钥签名
	 * 
	 * @param data
	 *            待签名数据
	 * @param priKey
	 *            签名私钥 PKCS8Encoded
	 * @return 签名结果
	 * @throws Exception
	 */
	public static byte[] sign(byte[] data, byte[] priKey) {
		byte[] sign = null;
		try {
			PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(priKey);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

			// 对数据进行SHA-256签名
			MessageDigest md = MessageDigest.getInstance("SHA-256");
			byte[] sha256Digest = md.digest(data);

			Signature instance = Signature.getInstance("SHA1withRSA");
			instance.initSign(privateKey);
			instance.update(sha256Digest);
			sign = instance.sign();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return sign;
	}

	/**
	 * 验证签名
	 * 
	 * @param data
	 *            待验签数据
	 * @param pubkey
	 *            公钥
	 * @param sign
	 *            签名
	 * @return
	 * @throws Exception
	 */
	public static boolean verify(byte[] data, byte[] pubkey, byte[] sign) {
		boolean result = false;
		try {
			// 获取公钥对象
			X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(pubkey);
			KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
			PublicKey pubKey = keyFactory.generatePublic(bobPubKeySpec);

			// 对数据进行SHA-256签名
			MessageDigest md = MessageDigest.getInstance("SHA-256");
			byte[] sha256Digest = md.digest(data);
			// System.out.println("sha256Digest"+Hex.encodeHexString(sha256Digest));
			// System.out.println("sign"+Hex.encodeHexString(sign));
			// 验证签名
			Signature instance = Signature.getInstance("SHA1withRSA");
			instance.initVerify(pubKey);
			instance.update(sha256Digest);
			result = instance.verify(sign);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return result;
	}

}